#!/usr/bin/env python
#
# host_menu.py
#
# Version : 0.7
# Date : 20080520
#
# Author : Bernard Czenkusz
# Email  : bernie@skipole.co.uk

# host_menu.py - Displays host menu panel and is a module in sm_gui
# package, run as part of the skipolemonitor gui interface
#
# Copyright (c) 2007 Bernard Czenkusz
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#


""" This is a module in the sm_gui package, and defines the Host menu panel

It is run as part of the skipolemonitor gui interface.
"""


import wx
import os
import ipv4_parse
import makehtml
from net import *


class Host(wx.Panel):
    """The Host menu, shown in the right panel when a host is selected"""
    def __init__(self, parent, sp):
        wx.Panel.__init__(self, parent)
        # sp is the splitter window holding this host
        self.item = 1
        self.sp = sp
        #
        # Initial menu values are set to 'Locahost' - as this is not shown
        # until a host is selected, the item set, and then all fields are
        # updated
        #
        # Create the sizer for this panel
        self.menu_sizer=wx.BoxSizer(wx.VERTICAL)
        #
        # Create FlexGridSizer for the text entry fields
        #
        self.host_fields_sizer=wx.FlexGridSizer(rows=0, cols=2, hgap=5, vgap=5)
        #
        # Short name text control
        # Label
        self.host_shortname_label=wx.StaticText(self, -1, "Short Name: ")
        self.host_fields_sizer.Add(self.host_shortname_label,
                                   0,
                                   wx.TOP | wx.LEFT | wx.ALIGN_TOP | wx.ALIGN_RIGHT,
                                   20)
        # Field
        self.host_shortname_field = wx.TextCtrl(self, -1, "Localhost")
        self.host_shortname_field.SetMinSize((150,-1))
        self.host_shortname_field.SetToolTipString("Host name, maximum\n12 characters.")
        self.host_fields_sizer.Add(self.host_shortname_field,
                                   0,
                                   wx.TOP | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT,
                                   20)
        #
        # Description text control
        # Label
        self.host_description_label=wx.StaticText(self, -1, "Description: ")
        self.host_fields_sizer.Add(self.host_description_label,
                                   0,
                                   wx.TOP | wx.LEFT | wx.ALIGN_TOP | wx.ALIGN_RIGHT,
                                   20)
        # Field
        self.host_description_field = wx.TextCtrl(self, -1, "Localhost")
        self.host_description_field.SetMinSize((150,-1))
        self.host_fields_sizer.Add(self.host_description_field,
                                   0,
                                   wx.TOP | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT | wx.EXPAND,
                                   20)
        #
        # IP address
        # Label
        self.host_ip_label=wx.StaticText(self, -1, "IP Address: ")
        self.host_fields_sizer.Add(self.host_ip_label,
                                   0,
                                   wx.TOP | wx.LEFT | wx.ALIGN_TOP | wx.ALIGN_RIGHT,
                                   20)
        # Field
        self.host_ip_field = wx.TextCtrl(self, -1, "127.0.0.1")
        self.host_ip_field.SetMinSize((150,-1))
        self.host_fields_sizer.Add(self.host_ip_field,
                                   0,
                                   wx.TOP | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT,
                                   20)
        #
        # Email Alert Enabled
        # Label
        self.host_email_label=wx.StaticText(self, -1, "Enable Email Alert: ")
        self.host_fields_sizer.Add(self.host_email_label,
                                   0,
                                   wx.TOP | wx.LEFT | wx.ALIGN_TOP | wx.ALIGN_RIGHT,
                                   20)
        # Field
        self.host_email_field = wx.CheckBox(self, -1, "Send email if this host changes status")
        self.host_fields_sizer.Add(self.host_email_field,
                                   0,
                                   wx.TOP | wx.RIGHT | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT,
                                   20)
        #
        self.host_email_field.SetValue(0)
        #
        # Make column 1 growable - this allows the right hand description field to grow
        self.host_fields_sizer.AddGrowableCol(1,0)
        #
        # And nest the FlexGridSizer as the first row of the menu_sizer
        self.menu_sizer.Add(self.host_fields_sizer, 0, wx.EXPAND)
        #
        # Buttons
        #
        button_size = (150,30)
        #
        # Apply button
        self.host_apply_button = wx.Button(self, label="Apply", size=button_size)
        self.host_apply_button.Enable(False)
        self.host_apply_button.SetToolTipString("Click to apply changes.")
        self.menu_sizer.Add(self.host_apply_button, 0, wx.ALL | wx.ALIGN_CENTER, 10)
        #
        # Delete this host button
        self.delete_host_button = wx.Button(self, label="Delete this host", size=button_size)
        self.menu_sizer.Add(self.delete_host_button, 0, wx.ALL | wx.ALIGN_CENTER, 10)
        #
        # Graph image
        graph_file=os.path.join(SCRIPTDIRECTORY,"gui_graph.png")
        self.bmp = wx.Image(graph_file, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
        self.graph_image=wx.StaticBitmap(self, -1, self.bmp)
        self.menu_sizer.Add(self.graph_image, 0, wx.ALL | wx.ALIGN_CENTER, 10)
        #
        #
        # Set the size to the panel
        self.SetSizer(self.menu_sizer)
        #
        #
        # Create bindings
        self.Bind(wx.EVT_TEXT, self.host_shortname, self.host_shortname_field)
        self.Bind(wx.EVT_TEXT, self.host_description, self.host_description_field)
        self.Bind(wx.EVT_TEXT, self.host_ip, self.host_ip_field)
        self.Bind(wx.EVT_CHECKBOX, self.host_email, self.host_email_field)
        self.Bind(wx.EVT_BUTTON, self.host_apply, self.host_apply_button)
        self.Bind(wx.EVT_BUTTON, self.delete_host, self.delete_host_button)


    def set_item(self, item):
        """Set the item for this host menu and update fields"""
        if not is_net_exists(item): return
        if is_net_group(item): return
        #
        self.item = item
        #
        self.host_shortname_field.SetValue(get_net(self.item, NAME))
        #
        self.host_description_field.SetValue(get_net(self.item, DESCRIPTION))
        #
        self.host_ip_field.SetValue(get_net(self.item, ADDRESS))
        #
        if get_net(self.item, EMAIL):
            self.host_email_field.SetValue(1)
        else:
            self.host_email_field.SetValue(0)
        #
        # Normally, if just selected, the apply button will be disabled
        self.host_apply_button.Enable(False)
        #
        self.update_graph()


    def update_graph(self):
        """Updates the graph in the host page"""
        if not is_net_exists(self.item): return
        if is_net_group(self.item): return
        # Graph image for this host
        graph_file=os.path.join(net_cfg["NETWORK_DATA_FOLDER"],str(self.item),"gui_graph.png")
        if not os.path.exists(graph_file):
            graph_file=os.path.join(SCRIPTDIRECTORY,"gui_graph.png")
        # update the image
        try:
            self.bmp = wx.Image(graph_file, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
            self.graph_image.SetBitmap(self.bmp)
        except:
            # If there's any problems, just pass
            pass

                
    # Host fields edited, limit their length, and enable
    # the Apply button

    def host_shortname(self, event):
        """Host short name menu item"""
        # Limit user input to 12 characters
        self.host_apply_button.Enable(True)
        text = event.GetString()
        if len(text)>12:
            pos=self.host_shortname_field.GetInsertionPoint()
            self.host_shortname_field.Remove(12,len(text)+1)
            self.host_shortname_field.SetInsertionPoint(pos)

    def host_description(self, event):
        """Host description menu item"""
        # Limit user input to 80 characters
        self.host_apply_button.Enable(True)
        text = event.GetString()
        if len(text)>80:
            pos=self.host_description_field.GetInsertionPoint()
            self.host_description_field.Remove(80,len(text)+1)
            self.host_description_field.SetInsertionPoint(pos)

    def host_ip(self, event):
        """Host IP address menu item"""
        # Limit user input to 15 characters
        self.host_apply_button.Enable(True)
        text = event.GetString()
        if len(text)>15:
            pos=self.host_ip_field.GetInsertionPoint()
            self.host_ip_field.Remove(15,len(text)+1)
            self.host_ip_field.SetInsertionPoint(pos)

    def host_email(self, event):
        """Host Email checkbox toggled"""
        self.host_apply_button.Enable(True)
        return


    # The host apply button is pressed

    def host_apply(self, event):
        """Apply button - host short name, description and IP address"""
        #
        # disable the Apply button
        self.host_apply_button.Enable(False)
        # get tree item currently selected
        tree_item = self.sp.tree.GetSelection()
        #
        # IP Address
        # Test IP address first, since if it is wrong, need to return
        # from this function without implementing any changes
        ip=self.host_ip_field.GetValue()
        ip=str(ip).strip()
        # check ip
        if ipv4_parse.parse(ip, 32) == 0:
            wx.MessageBox("The IP Address is incorrect!",
                          caption="Error",
                          style=wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP)
            # Put the textctrl back to the original ip address
            self.host_ip_field.SetValue(get_net(self.item, ADDRESS))
            return
        #
        # apply ip to the network dictionary
        if get_net(self.item, ADDRESS) != ip:
            set_net(self.item, ADDRESS, ip)
            # As the ip address has changed, must put status to zero
            set_net(self.item, STATUS, 0)
        #
        # Short Name
        text=self.host_shortname_field.GetValue()
        text=str(text).strip()
        #
        # apply Short name to the tree item which is currently selected
        self.sp.tree.SetItemText(tree_item, text)
        # apply to the network dictionary
        set_net(self.item, NAME, text)
        #
        # Description
        text=self.host_description_field.GetValue()
        text=str(text).strip()
        # apply description to the network dictionary
        set_net(self.item, DESCRIPTION, text)
        #
        # Email alerts
        if self.host_email_field.GetValue():
            set_net(self.item, EMAIL, 1)
        else:
            set_net(self.item, EMAIL, 0)
        #
        # Save to disc
        if not save_network():
            wx.MessageBox("ERROR: Unable to save changes to disk",
                          caption="ERROR",
                          style=wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP)
        # Flag the html pages need refreshing
        set_flag_html_refresh()
        return


    def delete_host(self, event):
        """Delete this host"""
        #
        # get tree item currently selected
        tree_item = self.sp.tree.GetSelection()
        #
        # Message Box
        short_name=get_net(self.item, NAME)
        retCode=wx.MessageBox("Are you sure you wish to\ndelete \"%s\"" % short_name,
                              "Delete Host",
                              wx.YES_NO | wx.ICON_QUESTION | wx.STAY_ON_TOP)
        if retCode != wx.YES : return
        #
        # Remove its ping data folder and contents
        makehtml.del_html_page(self.item)
        #
        # delete it from network
        del_net_item(self.item)
        #
        # Save to disc
        if not save_network():
            wx.MessageBox("ERROR: Unable to save changes to disk",
                          caption="ERROR",
                          style=wx.OK | wx.ICON_ERROR | wx.STAY_ON_TOP)
        # Request an HTML pages refresh
        set_flag_html_refresh()
        #
        # Delete from tree
        self.sp.tree.Delete(tree_item)
        # On an item being deleted, a new item is automatically selected
        tree_item = self.sp.tree.GetSelection()
        # get the dictionary item
        self.item=self.sp.tree.GetItemPyData(tree_item)
        return



